有两种格式可以在shell中创建函数:
采用关键字function,后跟分配给该代码块的函数名:
123function name {commands}更加接近于其他编程语言中定义函数的方式:
123name() {commands}
要在脚本中使用函数,只需要像其他shell命令一样,在行中指定函数名就可以了:
1234567891011121314#!/bin/bash#using a function in a scriptfunction func1 {echo "This is an example of a function"}count=1while [ $count -le 5 ]dofunc1count=[ count + 1 ]doneecho "This is the end of the loop"func1echo "Now this is the end of the script"bash shell把函数当作一个小型脚本,运行结束时会返回一个退出状态码
默认退出状态码
默认情况下,函数的退出状态码是函数中最后一条命令返回的退出状态码,在函数执行结束后,可以用$?来确定函数的退出状态码
使用return命令
bash shell使用return命令来退出函数并返回特定的退出状态码,return命令允许你指定一个整数值来定义函数的退出状态码。
12345678#!/bin/bashfunction db1 {read -p "Enter a value: " valueecho "doubling the value"return $[ $value * 2 ]}db1echo "The new value is $?"使用这种方法从函数中返回值,需小心:
函数一结束就取返回值
退出状态码必须是0~255
如果在用$?变量提取函数返回值之前执行了其他命令,函数的返回值就会丢失。
使用函数输出,将函数的输出保存到变量中:result=’db1’,这个命令将db1函数的输出赋给$result变量:
1234567#!/bin/bashfunction db1{read -p "Enter a value: " valueecho $[ $value * 2 ]}result=$(db1)echo "The new value is $result"
函数可以使用标准的参数环境变量来表示命令行上传给函数的参数,例如函数名会在
$0
变量中定义,函数命令行上的任何参数都会通过$1
、$2
等定义,也可以用特殊变量$#
来判断传给函数的参数数目:123456789101112131415#!/bin/bashfunction addem {if [ $# -eq 0 ] || [ $# -gt 2 ]thenecho -1elif [ $# -eq 1 ]thenecho $[ $1 + $1 ]elseecho $[ $1 + $2 ]fi}echo -n "Adding 10 and 15: "value=$(addem 10 15)echo $value由于函数使用特殊参数环境变量作为自己的参数值,因此无法直接获取脚本在命令行中的参数值:
1234567891011#!/bin/bashfunction badfunc1 {echo $[ $1 * $2 ]}if [$# -eq 2]thenvalue=$(badfunc1)echo "The result is $value"elseecho "Usage: badtest1 a b"fi尽管函数也使用了
$1
和$2
变量,但它们和脚本主体中的$1
和$2
变量并不相同,要在函数中使用这些值,必须在调用函数时手动将它们传过去。1234567891011#!/bin/bashfunction func {echo $[ $1 * $2 ]}if [$# -eq 2]thenvalue=$(func $1 $2)echo "The result is $value"elseecho "Usage: badtest a b"fi在函数内部使用的任何变量都可以被声明为局部变量,只要在变量声明的前面加上local关键字即可:local temp,当然也可以在变量赋值语句中使用local关键字:
1local temp=[ value + 5 ]向函数传数组参数:
123456789#!/bin/bashfuncton testit {echo "The parameters are: $@"thisarray=$1echo "The received array is ${thisarray[*]}"}myarray=(1 2 3 4 5)echo "The original array is: ${myarray[*]}"testit $myarray1234$ ./badtest3The original array is: 1 2 3 4 5The parameters are: 1The received array is 1如果你试图将数组变量作为函数参数,函数只会取数组变量的第一个值,要解决这个问题,你可以将该数组变量的值分解成单个的值,然后将这些值作为函数参数使用,在函数内部,可以将所有的参数重新组合成一个新的变量:
123456789#!/bin/bashfunction testit {local newarraynewarray=('echo "$@"')echo "The new array value is: ${newarray[*]}"}myarray=(1 2 3 4 5)echo "The original array is ${myarray[*]}"testit ${myarray[*]}另一个例子如下:
12345678910111213141516#!/bin/bashfunction addarray {local sum=0local newarraynewarray=($(echo "$@"))for value in ${newarray[*]}dosum=$[ $sum + $value ]doneecho $sum}myarray=(1 2 3 4 5)echo "The original array is ${myarray[*]}"arg1=$(echo {myarray[*]})result=$(addarray arg1)echo "The result is $result"从函数里向shell脚本传回数组变量可以使用echo语句按正确顺序输出单个数组值,然后脚本再将它们放进一个新的数组变量中:
12345678910111213141516171819#!/bin/bashfunction arraydblr {local orginarraylocal newarraylocal elementslocal ioriginarray=((echo "$@"))newarray=((echo "$@"))elements=[ $# - 1 ]for (( i = 0; i <= $elements; i++ )) {newarray[$i]=$[ ${originarray[$i]} * 2 ]}echo ${newarray[*]}}myarray=(1 2 3 4 5)echo "The original array is: ${myarray[*]}"arg1=(echo ${myarray[*]})result=($(arraydblr arg1))echo "The new array is: ${result[*]}"给一个递归的例子:
1234567891011121314#!/bin/bashfunction factorial {if [ $1 -eq 1 ]thenecho 1elselocal temp=$[ $1 - 1 ]local result=$(factorial $temp)echo $[ $result * $1 ]fi}read -p "Enter value: " valueresult=(factorial $value)echo "The factorial of value is: $result"bash shell 允许创建库文件,然后在多个脚本中引用该库文件,这个过程的第一步就是创建一个包含脚本中所需函数的公用库文件:
12345678910111213141516$cat myfuncsfunction addem {echo $[ $1 + $2 ]}function multem {echo $[ $1 * $2 ]}function divem {if ($2 -ne 0)thenecho $[ $1 / $2 ]elseecho -1fi}下一步就是在用到这些函数的脚本文件中包含myfuncs库文件,和环境变量一样,shell函数仅在定义它的shell会话内有效,如果你在shell命令行界面的提示符下运行myfuncs shell脚本,shell会创建一个新的shell并在其中运行这个脚本,它会为那个新的shell定义这三个函数,但当你运行另外一个要用到这些函数的脚本时,它们是无法使用的。
使用函数库的关键在于source命令,source命令会在当前shell上下文中执行命令,而不是创建一个新的shell,可以用source命令在shell脚本中运行库文件脚本,这样脚本就可以使用库中的函数了。
source命令有个快捷的别名,称作点操作符,要在shell脚本中运行myfuncs库文件,只需要这样:. ./myfuncs:
12345678910#!/bin/bash. ./myfuncsvalue1=10value2=5result1=(addem $value1 $value2)result2=(multem $value1 $value2)result3=(diven $value1 $value2)echo "The result of adding them is: $result1"echo "The result of multiplying them is: $result2"echo "The result of dividing them is: $result3"在命令行上创建函数:
采用单行方式定义参数:
1234$ function divem { echo $[ $1 + $2 ]; }$ divem 100 520$当在命令行上定义函数时,需要在每个命令后面加上分号,这样shell就能知道在哪里是命令的起止了。
采用多行方式定义函数:
123456$ function multem {> echo [ 1 * $2 ]> }$ multem 2 510$在函数的尾部使用花括号,shell就会知道你已经完成了函数的定义。
在命令行上定义的函数在退出shell时函数就会消失,一个好的方法就是将函数定义在一个特定的位置,这个位置在每次启动一个新shell的时候,都会由shell重新载入。
可以将函数放在.bashrc中,有两种方法:
- 直接在.bashrc文件中定义函数
- 读取函数文件,只要是在shell脚本中,都可以使用source命令将库文件中的函数添加到你的.bashrc脚本中
更好的是,shell还会将定义好的函数传给子shell进程,这样一来,这些函数就自动能够用于该shell会话的任何sehll脚本了